#pragma once

#include <iostream>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <atomic>
#include <fstream>
#include "logger.hpp"
#include <vector>


namespace helper{
    class StringUtil{
      public:
      static size_t stringSpilt(const std::string &str, const std::string &seq, std::vector<std::string> &str_array)
      {
        if (seq.empty())
        {
          // 如果分隔符为空，直接将整个字符串作为结果
          str_array.push_back(str);
          return str_array.size();
        }
        int pos = 0, idx = 0;
        while (idx < str.size())
        {
          pos = str.find(seq, idx);
          if (pos == std::string::npos)
          {
            str_array.push_back(str.substr(idx));
            return str_array.size();
          }

          if (pos == idx)
          {
            idx = pos + seq.size();
            continue;
          }
          str_array.push_back(str.substr(idx, pos - idx));
          idx = pos + seq.size();
        }
        return str_array.size();
      }
    };
    class TimeUtil{
      public:
      //获取时间戳
      static std::string getTime(){
        struct timeval tmp_time;
        gettimeofday(&tmp_time,nullptr);
        return std::to_string(tmp_time.tv_sec);
      }
      //获取当前毫秒时间戳,配合外面的原子变量的自增，形成具有唯一性的后缀
      static std::string onlyTime(){
        struct timeval tmp_time;
        gettimeofday(&tmp_time,nullptr);
        return std::to_string(static_cast<long long>(tmp_time.tv_sec*1000) + tmp_time.tv_usec/1000);
      }
    };

    const std::string temp_path = "./temp/";
    class PathFile{
      public:
      static std::string addSuffix(const std::string& filename,const std::string& back){
        std::string path=temp_path;
        path+=filename;
        path+=back;
        return path;
      }
      //获取源文件名
      static std::string getSrc(const std::string& filename){
        return addSuffix(filename,".cpp");
      }
      //获取标准错误文件名
      static std::string getError(const std::string& filename){
        return addSuffix(filename,".stderro");
      }
      //获取标准输出文件名
      static std::string getOut(const std::string& filename){
        return addSuffix(filename,".stdOut");
      }
      //获取标准输入文件名
      static std::string getIn(const std::string& filename){
        return addSuffix(filename,".stdin");
      }
      //获取可执行程序文件名
      static std::string getTatget(const std::string& filename){
        return addSuffix(filename,"./exe");
      }
      //获取编译错误文件名
      static std::string getCompileError(const std::string& filename){
        return addSuffix(filename,".compile_error");
      }
    };
    class FileUtil{
        public:
        static bool isFileExists(const std::string& filename){
            struct stat it;
            int ret = stat(filename.c_str(),&it);
            if( ret == 0){
                return S_ISREG(it.st_mode);
            }
            DLOG("目标文件[%s]不存在!",filename);
            return false;
        }/*使用stat函数来判断文件是否存在是一种很简便的方式，如果返回值为零，代表存在，否则不存在
         *但这样仍然会有一丝瑕疵，因为文件有很多种，我们需要结合实际情况进行二次判断，主要是检查struct stat结构体对象的st_mode
         * 对其判断是否为我们需要的种类*/
        static std::string getOnlyFile(){
            //生成唯一文件名，用于标识文件的唯一性
            std::atomic_uint id;//原子变量
            id++;
            std::string time_ms = TimeUtil::onlyTime();
            std::string uuid = std::to_string( id );
            return ( time_ms + "_" + uuid );
        }
        static bool fileWrite(const std::string& filename,const std::string& in){
            std::ofstream tmp_file (filename);
            if(!tmp_file.is_open()){
                //文件打开失败，回家吧，孩子
                ELOG("进行文件写入时,目标文件[%s]打开失败!",filename);
                return  false;
            }
            //打开成功，向文件中写入你想要的数据
            if( tmp_file.write(in.c_str(),in.size()) ){
                //写入成功
                return true;
            }
            DLOG("写入文件时,向目标文件[%s]写入失败!",filename);
            return false;
        }
        static bool fileRead(const std::string& filename, std::string& out,bool keep = false){
            std::ifstream tmp_file(filename);
            if( !tmp_file.is_open() ){
                //文件都打开不了，回家吧，孩子
                ELOG("读取文件时，目标文件[%s]打开失败!",filename);
                return false;
            }
            std::string line;
            while(std::getline(tmp_file,line)){
                out=out+line;
                if(keep){
                    out+="/n";
                }
            }
            return true;
        }
    };
}